from rest_framework import serializers
from geopy.distance import geodesic
import datetime

from alipaynfc.models import *
from merchants.models import *
from users.models import *


class NFCDeviceBountyQuestListModelSerializer(serializers.ModelSerializer):

    merchant = serializers.SerializerMethodField(read_only=True)
    sn = serializers.SerializerMethodField(read_only=True)
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    expired_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    validity = serializers.SerializerMethodField(read_only=True)
    quest_status_str = serializers.CharField(source='get_quest_status_display', read_only=True)
    quest_status = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = NFCDeviceBountyQuest
        fields = ('id', 'merchant', 'task_id', 'amount', 'sn', 'create_time', 'expired_time', 'validity', 'quest_status', 'quest_status_str',
                  'level_name')

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_quest_status(self, obj):
        if obj.quest_status in [0, 1]:
            if obj.expired_time <= datetime.datetime.now():
                obj.quest_status = 5
                obj.save()
                NFCDeviceBountyQuestSchedule.objects.filter(quest_id=obj.id, quest_status=obj.quest_status).update(quest_status=4, cancel_time=datetime.datetime.now())
        return obj.quest_status

    def get_validity(self, obj):
        try:
            return f'{obj.validity_count}{obj.get_validity_type_display()}'
        except:
            return ''

    def get_sn(self, obj):
        try:
            return obj.device.sn
        except:
            return ''

    def get_merchant(self, obj):
        data = {}
        try:
            merchant = obj.merchant
            data['id'] = merchant.id
            data['merchant_name'] = merchant.short_name
            data['business'] = merchant.wyfMerchantID
            data['address'] = merchant.store_address
        except:
            pass
        return data


class NFCDeviceBountyQuestRetrieveModelSerializer(serializers.ModelSerializer):

    merchant = serializers.SerializerMethodField(read_only=True)
    sn = serializers.SerializerMethodField(read_only=True)
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    expired_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    validity = serializers.SerializerMethodField(read_only=True)
    quest_status_str = serializers.CharField(source='get_quest_status_display', read_only=True)
    quest_status = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = NFCDeviceBountyQuest
        fields = ('id', 'merchant', 'task_id', 'amount', 'sn', 'create_time', 'expired_time', 'validity', 'quest_status', 'quest_status_str')

    def get_quest_status(self, obj):
        if obj.quest_status in [0, 1]:
            if obj.expired_time <= datetime.datetime.now():
                obj.quest_status = 5
                obj.save()
                NFCDeviceBountyQuestSchedule.objects.filter(quest_id=obj.id, quest_status=obj.quest_status).update(quest_status=4, cancel_time=datetime.datetime.now())
        return obj.quest_status

    def get_validity(self, obj):
        try:
            return f'{obj.validity_count}{obj.get_validity_type_display()}'
        except:
            return ''

    def get_sn(self, obj):
        try:
            return obj.device.sn
        except:
            return ''

    def get_merchant(self, obj):
        data = {}
        try:
            merchant = obj.merchant
            data['id'] = merchant.id
            data['merchant_name'] = merchant.short_name
            data['business'] = merchant.wyfMerchantID
            data['address'] = merchant.store_address
        except:
            pass
        return data


class NFCDeviceBountyQuestScheduleListModelSerializer(serializers.ModelSerializer):

    amount = serializers.SerializerMethodField(read_only=True)
    task_id = serializers.SerializerMethodField(read_only=True)
    merchant = serializers.SerializerMethodField(read_only=True)
    longitude = serializers.SerializerMethodField(read_only=True)
    latitude = serializers.SerializerMethodField(read_only=True)
    quest_status_str = serializers.CharField(source='get_quest_status_display', read_only=True)

    class Meta:
        model = NFCDeviceBountyQuestSchedule
        fields = ('id', 'amount', 'quest_status', 'quest_status_str', 'merchant', 'task_id', 'longitude', 'latitude')

    def get_longitude(self, obj):
        try:
            return obj.quest.longitude
        except:
            return ''

    def get_latitude(self, obj):
        try:
            return obj.quest.latitude
        except:
            return ''

    def get_amount(self, obj):
        try:
            return obj.quest.amount
        except:
            return '0'

    def get_merchant(self, obj):
        data = {}
        try:
            merchant = obj.quest.merchant
            data['merchant_name'] = merchant.name
            data['address'] = merchant.store_address
        except:
            pass
        return data

    def get_task_id(self, obj):
        try:
            return obj.quest.task_id
        except:
            return ''


class NFCDeviceBountyQuestScheduleRetrieveModelSerializer(serializers.ModelSerializer):

    amount = serializers.SerializerMethodField(read_only=True)
    task_id = serializers.SerializerMethodField(read_only=True)
    merchant = serializers.SerializerMethodField(read_only=True)
    quest_status_str = serializers.CharField(source='get_quest_status_display', read_only=True)
    appeal_status_str = serializers.CharField(source='get_appeal_status_display', read_only=True)
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    expired_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    cancel_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    appeal_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    success_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    assist_set = serializers.SerializerMethodField(read_only=True)
    award = serializers.SerializerMethodField(read_only=True)
    mobile = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = NFCDeviceBountyQuestSchedule
        fields = ('id', 'amount', 'quest_status', 'quest_status_str', 'merchant', 'task_id', 'appeal_explain', 'assist_set',
                  'create_time', 'expired_time', 'cancel_time', 'appeal_time', 'handle_time', 'handle_explain',
                  'award', 'appeal_status', 'appeal_status_str', 'success_time', 'mobile')

    def get_mobile(self, obj):
        try:
            return obj.customeruservice.mobile
        except:
            return ''

    def get_award(self, obj):
        data = {}
        data['id'] = ''
        data['state'] = ''
        data['received_time'] = ''
        data['return_msg'] = ''
        try:
            award = obj.award
            if award:
                data['id'] = award.id
                data['state'] = award.state
                data['amount'] = award.amount
                data['return_msg'] = award.return_msg
                data['received_time'] = award.received_time.strftime("%Y-%m-%d %H:%M:%S")
        except:
            pass
        return data

    def get_amount(self, obj):
        try:
            return obj.quest.amount
        except:
            return '0'

    def get_merchant(self, obj):
        data = {}
        try:
            merchant = obj.quest.merchant
            data['merchant_name'] = merchant.name
            data['address'] = merchant.store_address
            data['id'] = merchant.id
        except:
            pass
        return data

    def get_task_id(self, obj):
        try:
            return obj.quest.task_id
        except:
            return ''

    def get_assist_set(self, obj):
        data = []
        try:
            queryset = NFCDeviceBountyQuestScheduleAppealAssist.objects.filter(schedule_id=obj.id)
            for query in queryset:
                data.append(query.picture.url)
        except:
            pass
        return data


class NFCDeviceListModelSerializer(serializers.ModelSerializer):

    device_type_str = serializers.CharField(source='get_device_type_display', read_only=True)
    merchant_name = serializers.SerializerMethodField(read_only=True)
    business_no = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    lighten_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    poor_reach_days = serializers.SerializerMethodField(read_only=True)
    rewards_status_str = serializers.CharField(source='get_rewards_status_display', read_only=True)
    is_lighten_str = serializers.CharField(source='get_is_lighten_display', read_only=True)

    class Meta:
        model = NFCDevice
        fields = ['id', 'device_type', 'device_type_str', 'sn', 'merchant_name', 'business_no', 'level_name', 'lighten_time',
                  'reach_days', 'poor_reach_days', 'remain_days', 'distinct_user_num', 'rewards_status', 'rewards_status_str',
                  'is_lighten', 'is_lighten_str']

    def get_poor_reach_days(self, obj):
        poor_reach_days = 20 - obj.reach_days
        if poor_reach_days >= 0:
            return poor_reach_days
        else:
            return 0

    def get_merchant_name(self, obj):
        try:
            return obj.merchant.name
        except:
            return ''

    def get_business_no(self, obj):
        try:
            return obj.merchant.wyfMerchantID
        except:
            return ''

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''


class NFCDeviceRetrieveModelSerializer(serializers.ModelSerializer):

    device_type_str = serializers.CharField(source='get_device_type_display', read_only=True)
    merchant_name = serializers.SerializerMethodField(read_only=True)
    business_no = serializers.SerializerMethodField(read_only=True)
    level = serializers.SerializerMethodField(read_only=True)
    lighten_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    poor_reach_days = serializers.SerializerMethodField(read_only=True)
    rewards_status_str = serializers.CharField(source='get_rewards_status_display', read_only=True)
    is_lighten_str = serializers.CharField(source='get_is_lighten_display', read_only=True)
    distinct_user_status_str = serializers.CharField(source='get_distinct_user_status_display', read_only=True)
    reach_status_str = serializers.CharField(source='get_reach_status_display', read_only=True)
    schedule = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = NFCDevice
        fields = ['id', 'device_type', 'device_type_str', 'sn', 'merchant_name', 'business_no', 'level', 'lighten_time',
                  'reach_days', 'poor_reach_days', 'remain_days', 'distinct_user_num', 'rewards_status', 'rewards_status_str',
                  'is_lighten', 'is_lighten_str', 'distinct_user_status', 'distinct_user_status_str', 'work_user', 'schedule',
                  'alipay_num', 'total_amount', 'nfc_num', 'nfc_amount', 'reach_status', 'reach_status_str', 'merchant_id',
                  'address']

    def get_schedule(self, obj):
        data = []
        if obj.is_lighten == 1:
            statistics_time = NFCDeviceStatistics.objects.all().last().trade_time
            lighten_time = obj.lighten_time
            end_lighten_time = lighten_time + datetime.timedelta(days=29)
            begin_lighten_time = lighten_time.strftime("%Y-%m-%d 00:00:00")
            queryset = NFCDeviceStatistics.objects.filter(device_id=obj.id, trade_time__lte=end_lighten_time, trade_time__gte=begin_lighten_time)
            check_data = {}
            for query in queryset:
                check_data[query.trade_time.strftime("%m.%d")] = {"is_reach": query.is_reach, "id": query.id, "alipay_num": query.alipay_num, "total_amount": query.total_amount, "nfc_num": query.nfc_num, "nfc_amount": query.nfc_amount}
                check_data[f'{query.trade_time.strftime("%m.%d")}_id'] = query.id
            for i in range(30):
                child_data = {}
                child_data['days'] = lighten_time.strftime("%m.%d")
                if lighten_time.strftime("%m.%d") in check_data:
                    child_data['is_reach'] = check_data[lighten_time.strftime("%m.%d")]['is_reach']
                    child_data['statistics_id'] = check_data[lighten_time.strftime("%m.%d")]['id']
                    child_data['alipay_num'] = check_data[lighten_time.strftime("%m.%d")]['alipay_num']
                    child_data['total_amount'] = check_data[lighten_time.strftime("%m.%d")]['total_amount']
                    child_data['nfc_num'] = check_data[lighten_time.strftime("%m.%d")]['nfc_num']
                    child_data['nfc_amount'] = check_data[lighten_time.strftime("%m.%d")]['nfc_amount']
                else:
                    child_data['is_reach'] = 2
                if lighten_time.strftime("%Y-%m-%d") == datetime.datetime.now().strftime("%Y-%m-%d"):
                    child_data['today'] = 1
                if statistics_time.strftime("%Y-%m-%d") == lighten_time.strftime("%Y-%m-%d"):
                    child_data['statistics_day'] = 1
                data.append(child_data)
                lighten_time = lighten_time + datetime.timedelta(days=1)
        return data

    def get_poor_reach_days(self, obj):
        poor_reach_days = 20 - obj.reach_days
        if poor_reach_days >= 0:
            return poor_reach_days
        else:
            return 0

    def get_merchant_name(self, obj):
        try:
            return f'{obj.merchant.name}({obj.merchant.short_name})'
        except:
            return ''

    def get_business_no(self, obj):
        try:
            return obj.merchant.wyfMerchantID
        except:
            return ''

    def get_level(self, obj):
        try:
            level = obj.level
            return f'{level.city_name}/{level.district_name}/{level.branch_name}'
        except:
            return ''


class MerchantNFCDeviceTradeListModelSerializer(serializers.ModelSerializer):

    trade_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    pay_type_str = serializers.CharField(source='get_pay_type_display', read_only=True)
    is_effective = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = MerchantNFCDeviceTrade
        fields = ['id', 'transaction_id', 'trade_time', 'trade_amount', 'smid', 'pay_type', 'pay_type_str', 'is_effective']

    def get_is_effective(self, obj):
        if obj.trade_amount >= Decimal('3') and obj.pay_type == 1:
            return 1
        else:
            return 0
